import java.util.*;

public class Area implements Lookable
{
	private String name;
	private String description;
	private ArrayList<Place> places;

	public Area(String name) {
		this.name = name;
		this.description = "DEFAULT DESCRIPTION";
		this.places = new ArrayList<Place>();
	}

	public Area(String name, String description, ArrayList<Place> places) {
		this.name = name;
		this.description = description;
		this.places = places;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String look() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}
	
	public ArrayList<Place> getPlaces() {
		return places;
	}
	
	public void addPlace(Place place) {
		Location placeLoc = place.getLocation();
		for(Place p : places) {
			if(placeLoc.equals(p.getLocation())) {
				return;
			}
		}
		places.add(place);
	}
	
	public void removePlace(Place p) {
		places.remove(p);
	}
	
	public void addPlayer(Player player)
	{
		int random = (int)(Math.random()*places.size());
		places.get(random).addEntity(player);
	}
	
	/*
	 * @return the Place that the Player is currently in
	 */
	public Place playerPlace(Player player) {
		ArrayList<Place> places = getPlaces();
		for(Place p : places) {
			if(p.getEntities().contains(player)) {
				return p;
			}
		}
		return null;
	}
	
	/*
	 * @return the Place at the specified Location
	 */
	public Place getPlaceAt(Location loc) {
		for(Place p : places) {
			if(loc.equals(p.getLocation())) {
				return p;
			}
		}
		return null;
	}
	
	/*
	 * @return an ArrayList of Places adjacent (in a cardinal direction) to the given Place
	 */
	public ArrayList<Place> getAdjacentPlacesTo(Place place) {
		ArrayList<Place> places = new ArrayList<Place>();
		ArrayList<Location> adjacentLocs = place.getLocation().getAdjacentLocations();
		for(Location loc : adjacentLocs) {
			if(GameUtils.directions.contains(place.getLocation().getDirectionTowards(loc).toLowerCase())) {
				Place newPlace = getPlaceAt(loc);
				if(newPlace != null) {
					places.add(newPlace);
				}
			}
		}
		return places;
	}
	
	/*
	 * @return an ArrayList of directions that one can leave the given Place from
	 */
	public ArrayList<String> getValidCardinalDirectionsFrom(Place place) {
		ArrayList<String> directions = new ArrayList<String>();
		ArrayList<Place> adjacentPlaces = getAdjacentPlacesTo(place);
		Location placeLoc = place.getLocation();
		
		for(Place p : adjacentPlaces) {
			String newDir = placeLoc.getDirectionTowards(p.getLocation());
			if(GameUtils.directions.contains(newDir.toLowerCase())) {
				directions.add(newDir);
			}
		}
		return directions;
	}
	
	/*
	 * fills area with a bunch up randomly located Places and cleans up inaccessible ones
	 */
	public void createPlaces(int maxAmount) {
		for(int i=0;i < maxAmount;i++) {
			int xRand = (int)(Math.random()*maxAmount/3);
			int yRand = (int)(Math.random()*maxAmount/3);
			Place newPlace = new Place("place" + i, new Location(xRand, yRand));
			addPlace(newPlace);
		}
		tidyUpPlaces();
	}
	
	/*
	 * removes all Places with no adjacent Places (i.e., inaccessible Places)
	 */
	private void tidyUpPlaces() {
		for(int i=0; i < places.size();i++) {
			ArrayList<Place> adjacentPlaces = getAdjacentPlacesTo(places.get(i));
			if(adjacentPlaces.size() == 0) {
				removePlace(places.get(i));
				i--;
			}
		}
	}
}